home *** CD-ROM | disk | FTP | other *** search
/ STraTOS 1997 April & May / STraTOS 1 - 1997 April & May.iso / CD01 / INTERNET / SITES / LITTLE / P3SRC.ZIP / ATARI / IMAGE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-18  |  28.3 KB  |  1,433 lines

  1. /****************************************************************************
  2. *                image.c
  3. *
  4. *  This module implements the mapped textures including image map, bump map
  5. *  and material map.
  6. *
  7. *  from Persistence of Vision(tm) Ray Tracer
  8. *  Copyright 1996 Persistence of Vision Team
  9. *---------------------------------------------------------------------------
  10. *  NOTICE: This source code file is provided so that users may experiment
  11. *  with enhancements to POV-Ray and to port the software to platforms other
  12. *  than those supported by the POV-Ray Team.  There are strict rules under
  13. *  which you are permitted to use this file.  The rules are in the file
  14. *  named POVLEGAL.DOC which should be distributed with this file. If
  15. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  16. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  17. *  Forum.  The latest version of POV-Ray may be found there as well.
  18. *
  19. * This program is based on the popular DKB raytracer version 2.12.
  20. * DKBTrace was originally written by David K. Buck.
  21. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  22. *
  23. *****************************************************************************/
  24.  
  25. #include "frame.h"
  26. #include "vector.h"
  27. #include "povproto.h"
  28. #include "texture.h"
  29. #include "image.h"
  30. #include "matrices.h"
  31. #include "povray.h"
  32.  
  33.  
  34.  
  35. /*****************************************************************************
  36. * Local preprocessor defines
  37. ******************************************************************************/
  38.  
  39.  
  40.  
  41. /*****************************************************************************
  42. * Local typedefs
  43. ******************************************************************************/
  44.  
  45.  
  46.  
  47. /*****************************************************************************
  48. * Local variables
  49. ******************************************************************************/
  50.  
  51.  
  52.  
  53. /*****************************************************************************
  54. * Static functions
  55. ******************************************************************************/
  56.  
  57. static int cylindrical_image_map PARAMS((VECTOR EPoint, IMAGE * Image, DBL *u, DBL *v));
  58. static int torus_image_map PARAMS((VECTOR EPoint, IMAGE * Image, DBL *u, DBL *v));
  59. static int spherical_image_map PARAMS((VECTOR EPoint, IMAGE * Image, DBL *u, DBL *v));
  60. static int planar_image_map PARAMS((VECTOR EPoint, IMAGE * Image, DBL *u, DBL *v));
  61. static void no_interpolation PARAMS((IMAGE * Image, DBL xcoor, DBL ycoor, COLOUR colour, int *index));
  62. static DBL bilinear PARAMS((DBL *corners, DBL x, DBL y));
  63. static DBL norm_dist PARAMS((DBL *corners, DBL x, DBL y));
  64. static void Interp PARAMS((IMAGE * Image, DBL xcoor, DBL ycoor, COLOUR colour, int *index));
  65. static void image_colour_at PARAMS((IMAGE * Image, DBL xcoor, DBL ycoor, COLOUR colour, int *index));
  66. static int map PARAMS((VECTOR EPoint, TPATTERN * Turb, DBL *xcoor, DBL *ycoor));
  67.  
  68. /*
  69.  * 2-D to 3-D Procedural Texture Mapping of a Bitmapped Image onto an Object:
  70.  * 
  71.  * A. Simplistic (planar) method of image projection devised by DKB and AAC:
  72.  * 
  73.  * 1. Transform texture in 3-D space if requested. 2. Determine local object 2-d
  74.  * coords from 3-d coords by <X Y Z> triple. 3. Return pixel color value at
  75.  * that position on the 2-d plane of "Image". 3. Map colour value in Image
  76.  * [0..255] to a more normal colour range [0..1].
  77.  * 
  78.  * B. Specialized shape projection variations by Alexander Enzmann:
  79.  * 
  80.  * 1. Cylindrical mapping 2. Spherical mapping 3. Torus mapping
  81.  */
  82.  
  83. /*****************************************************************************
  84. *
  85. * FUNCTION
  86. *
  87. *   image_map
  88. *
  89. * INPUT
  90. *
  91. *   EPoint   -- 3-D point at which function is evaluated
  92. *   Pigment  -- Pattern containing various parameters
  93. *
  94. * OUTPUT
  95. *
  96. *   Colour   -- color at EPoint
  97. *
  98. * RETURNS
  99. *
  100. *   int - TRUE,  if current point on the image map
  101. *         FALSE, if current point is not on the image map
  102. *
  103. * AUTHOR
  104. *
  105. *   POV-Ray Team
  106. *
  107. * DESCRIPTION   : Determines color of a 3-D point from a 2-D bitmap
  108. *
  109. * CHANGES
  110. *
  111. ******************************************************************************/
  112.  
  113. int image_map(EPoint, Pigment, colour)
  114. VECTOR EPoint;
  115. PIGMENT *Pigment;
  116. COLOUR colour;
  117. {
  118.   int reg_number;
  119.   DBL xcoor = 0.0, ycoor = 0.0;
  120.  
  121.   /* If outside map coverage area, return clear */
  122.  
  123.   if (map(EPoint, ((TPATTERN *) Pigment), &xcoor, &ycoor))
  124.   {
  125.     Make_ColourA(colour, 1.0, 1.0, 1.0, 0.0, 1.0);
  126.  
  127.     return(FALSE);
  128.   }
  129.   else
  130.   {
  131.     image_colour_at(Pigment->Vals.Image, xcoor, ycoor, colour, ®_number);
  132.   }
  133.  
  134.   return(TRUE);
  135. }
  136.  
  137.  
  138.  
  139. /*****************************************************************************
  140. *
  141. * FUNCTION
  142. *
  143. * INPUT
  144. *
  145. * OUTPUT
  146. *
  147. * RETURNS
  148. *
  149. * AUTHOR
  150. *
  151. * DESCRIPTION
  152. *
  153. *   Very different stuff than the other routines here. This routine takes an
  154. *   intersection point and a texture and returns a new texture based on the
  155. *   index/color of that point in an image/materials map. CdW 7/91
  156. *
  157. * CHANGES
  158. *
  159. ******************************************************************************/
  160.  
  161. TEXTURE *material_map(EPoint, Texture)
  162. VECTOR EPoint;
  163. TEXTURE *Texture;
  164. {
  165.   int reg_number = 0;
  166.   int Material_Number;
  167.   int numtex;
  168.   DBL xcoor = 0.0, ycoor = 0.0;
  169.   COLOUR colour;
  170.   TEXTURE *Temp_Tex;
  171.  
  172.   /*
  173.    * Now we have transformed x, y, z we use image mapping routine to determine
  174.    * texture index.
  175.    */
  176.  
  177.   if (map(EPoint, ((TPATTERN *) Texture), &xcoor, &ycoor))
  178.   {
  179.     Material_Number = 0;
  180.   }
  181.   else
  182.   {
  183.     Make_ColourA(colour, 0.0, 0.0, 0.0, 0.0, 0.0);
  184.  
  185.     image_colour_at(Texture->Vals.Image, xcoor, ycoor, colour, ®_number);
  186.  
  187.     if (Texture->Vals.Image->Colour_Map == NULL)
  188.     {
  189.       Material_Number = (int)(colour[RED] * 255.0);
  190.     }
  191.     else
  192.     {
  193.       Material_Number = reg_number;
  194.     }
  195.   }
  196.  
  197.   if (Material_Number > Texture->Num_Of_Mats)
  198.   {
  199.     Material_Number %= Texture->Num_Of_Mats;
  200.   }
  201.  
  202.   for (numtex = 0, Temp_Tex = Texture->Materials;
  203.        (Temp_Tex->Next_Material != NULL) && (numtex < Material_Number);
  204.        Temp_Tex = Temp_Tex->Next_Material, numtex++)
  205.   {
  206.     /* do nothing */
  207.   }
  208.  
  209.   return (Temp_Tex);
  210. }
  211.  
  212.  
  213.  
  214. /*****************************************************************************
  215. *
  216. * FUNCTION
  217. *
  218. * INPUT
  219. *
  220. * OUTPUT
  221. *
  222. * RETURNS
  223. *
  224. * AUTHOR
  225. *
  226. * DESCRIPTION
  227. *
  228. * CHANGES
  229. *
  230. ******************************************************************************/
  231.  
  232. void bump_map(EPoint, Tnormal, normal)
  233. VECTOR EPoint;
  234. TNORMAL *Tnormal;
  235. VECTOR normal;
  236. {
  237.   DBL xcoor = 0.0, ycoor = 0.0;
  238.   int index, index2, index3;
  239.   COLOUR colour1, colour2, colour3;
  240.   VECTOR p1, p2, p3;
  241.   VECTOR bump_normal;
  242.   VECTOR xprime, yprime, zprime, Temp;
  243.   DBL Length;
  244.   DBL Amount = Tnormal->Amount;
  245.   IMAGE *Image = Tnormal->Vals.Image;
  246.  
  247.   Make_ColourA(colour1, 0.0, 0.0, 0.0, 0.0, 0.0);
  248.   Make_ColourA(colour2, 0.0, 0.0, 0.0, 0.0, 0.0);
  249.   Make_ColourA(colour3, 0.0, 0.0, 0.0, 0.0, 0.0);
  250.  
  251.   /* going to have to change this */
  252.   /* need to know if bump point is off of image for all 3 points */
  253.  
  254.   if (map(EPoint, (TPATTERN *) Tnormal, &xcoor, &ycoor))
  255.   {
  256.     return;
  257.   }
  258.   else
  259.   {
  260.     image_colour_at(Image, xcoor, ycoor, colour1, &index);
  261.   }
  262.  
  263.   xcoor--;
  264.   ycoor++;
  265.  
  266.   if (xcoor < 0.0)
  267.   {
  268.     xcoor += (DBL)Image->iwidth;
  269.   }
  270.   else
  271.   {
  272.     if (xcoor >= Image->iwidth)
  273.     {
  274.       xcoor -= (DBL)Image->iwidth;
  275.     }
  276.   }
  277.  
  278.   if (ycoor < 0.0)
  279.   {
  280.     ycoor += (DBL)Image->iheight;
  281.   }
  282.   else
  283.   {
  284.     if (ycoor >= (DBL)Image->iheight)
  285.     {
  286.       ycoor -= (DBL)Image->iheight;
  287.     }
  288.   }
  289.  
  290.   image_colour_at(Image, xcoor, ycoor, colour2, &index2);
  291.  
  292.   xcoor += 2.0;
  293.  
  294.   if (xcoor < 0.0)
  295.   {
  296.     xcoor += (DBL)Image->iwidth;
  297.   }
  298.   else
  299.   {
  300.     if (xcoor >= Image->iwidth)
  301.     {
  302.       xcoor -= (DBL)Image->iwidth;
  303.     }
  304.   }
  305.  
  306.   image_colour_at(Image, xcoor, ycoor, colour3, &index3);
  307.  
  308.   if (Image->Colour_Map == NULL || Image->Use_Colour_Flag)
  309.   {
  310.     p1[X] = 0;
  311.     p1[Y] = Amount * (0.229 * colour1[RED] + 0.587 * colour1[GREEN] + 0.114 * colour1[BLUE]);
  312.     p1[Z] = 0;
  313.  
  314.     p2[X] = 0;
  315.     p2[Y] = Amount * (0.229 * colour2[RED] + 0.587 * colour2[GREEN] + 0.114 * colour2[BLUE]);
  316.     p2[Z] = 1;
  317.  
  318.     p3[X] = 1;
  319.     p3[Y] = Amount * (0.229 * colour3[RED] + 0.587 * colour3[GREEN] + 0.114 * colour3[BLUE]);
  320.     p3[Z] = 1;
  321.   }
  322.   else
  323.   {
  324.     p1[X] = 0;
  325.     p1[Y] = Amount * index;
  326.     p1[Z] = 0;
  327.  
  328.     p2[X] = 0;
  329.     p2[Y] = Amount * index2;
  330.     p2[Z] = 1;
  331.  
  332.     p3[X] = 1;
  333.     p3[Y] = Amount * index3;
  334.     p3[Z] = 1;
  335.   }
  336.  
  337.   /* we have points 1,2,3 for a triangle now we need the surface normal for it */
  338.  
  339.   VSub(xprime, p1, p2);
  340.   VSub(yprime, p3, p2);
  341.   VCross(bump_normal, yprime, xprime);
  342.   VNormalize(bump_normal, bump_normal);
  343.  
  344.   Assign_Vector(yprime, normal);
  345.   Make_Vector(Temp, 0.0, 1.0, 0.0);
  346.   VCross(xprime, yprime, Temp);
  347.   VLength(Length, xprime);
  348.  
  349.   if (Length < EPSILON)
  350.   {
  351.     if (fabs(normal[Y] - 1.0) < Small_Tolerance)
  352.     {
  353.       Make_Vector(yprime, 0.0, 1.0, 0.0);
  354.       Make_Vector(xprime, 1.0, 0.0, 0.0);
  355.       Length = 1.0;
  356.     }
  357.     else
  358.     {
  359.       Make_Vector(yprime, 0.0, -1.0, 0.0);
  360.       Make_Vector(xprime, 1.0, 0.0, 0.0);
  361.       Length = 1.0;
  362.     }
  363.   }
  364.  
  365.   VScaleEq(xprime, 1.0 / Length);
  366.   VCross(zprime, xprime, yprime);
  367.   VNormalizeEq(zprime);
  368.   VScaleEq(xprime, bump_normal[X]);
  369.   VScaleEq(yprime, bump_normal[Y]);
  370.   VScaleEq(zprime, bump_normal[Z]);
  371.   VAdd(Temp, xprime, yprime);
  372.   VAdd(normal, Temp, zprime);
  373. }
  374.  
  375.  
  376.  
  377. /*****************************************************************************
  378. *
  379. * FUNCTION
  380. *
  381. * INPUT
  382. *
  383. * OUTPUT
  384. *
  385. * RETURNS
  386. *
  387. * AUTHOR
  388. *
  389. * DESCRIPTION
  390. *
  391. * CHANGES
  392. *
  393. ******************************************************************************/
  394.  
  395. static void image_colour_at(Image, xcoor, ycoor, colour, index)
  396. IMAGE *Image;
  397. DBL xcoor, ycoor;
  398. COLOUR colour;
  399. int *index;
  400. {
  401.   switch (Image->Interpolation_Type)
  402.   {
  403.     case NO_INTERPOLATION:
  404.  
  405.       no_interpolation(Image, xcoor, ycoor, colour, index);
  406.  
  407.       break;
  408.  
  409.     default:
  410.  
  411.       Interp(Image, xcoor, ycoor, colour, index);
  412.  
  413.       break;
  414.   }
  415. }
  416.  
  417.  
  418.  
  419. /*****************************************************************************
  420. *
  421. * FUNCTION
  422. *
  423. * INPUT
  424. *
  425. * OUTPUT
  426. *
  427. * RETURNS
  428. *
  429. * AUTHOR
  430. *
  431. * DESCRIPTION
  432. *
  433. *   Map a point (x, y, z) on a cylinder of radius 1, height 1, that has its axis
  434. *   of symmetry along the y-axis to the square [0,1]x[0,1].
  435. *
  436. * CHANGES
  437. *
  438. ******************************************************************************/
  439.  
  440. static int cylindrical_image_map(EPoint, Image, u, v)
  441. VECTOR EPoint;
  442. IMAGE *Image;
  443. DBL *u, *v;
  444. {
  445.   DBL len, theta;
  446.   DBL rdiv;
  447.   DBL x = EPoint[X];
  448.   DBL y = EPoint[Y];
  449.   DBL z = EPoint[Z];
  450.  
  451.   if ((Image->Once_Flag) && ((y < 0.0) || (y > 1.0)))
  452.   {
  453.     return 0;
  454.   }
  455.  
  456.   *v = fmod(y * Image->height, Image->height);
  457.  
  458.   /* Make sure this vector is on the unit sphere. */
  459.  
  460.   len = sqrt(x * x + y * y + z * z);
  461.  
  462.   if (len == 0.0)
  463.   {
  464.     return 0;
  465.   }
  466.   else
  467.   {
  468.     rdiv = (1.0 / len);
  469.     x *= rdiv;
  470.     z *= rdiv;
  471. /*
  472.     x /= len;
  473.     z /= len;
  474. */
  475.   }
  476.  
  477.   /* Determine its angle from the point (1, 0, 0) in the x-z plane. */
  478.  
  479.   len = sqrt(x * x + z * z);
  480.  
  481.   if (len == 0.0)
  482.   {
  483.     return 0;
  484.   }
  485.   else
  486.   {
  487.     if (z == 0.0)
  488.     {
  489.       if (x > 0)
  490.       {
  491.         theta = 0.0;
  492.       }
  493.       else
  494.       {
  495.         theta = M_PI;
  496.       }
  497.     }
  498.     else
  499.     {
  500.       theta = acos(x / len);
  501.  
  502.       if (z < 0.0)
  503.       {
  504.         theta = 2.0 * M_PI - theta;
  505.       }
  506.     }
  507.  
  508.     theta /= 2.0 * M_PI;  /* This will be from 0 to 1 */
  509.   }
  510.  
  511.   *u = (theta * Image->width);
  512.  
  513.   return 1;
  514. }
  515.  
  516.  
  517.  
  518. /*****************************************************************************
  519. *
  520. * FUNCTION
  521. *
  522. * INPUT
  523. *
  524. * OUTPUT
  525. *
  526. * RETURNS
  527. *
  528. * AUTHOR
  529. *
  530. * DESCRIPTION
  531. *
  532. *   Map a point (x, y, z) on a torus  to a 2-d image.
  533. *
  534. * CHANGES
  535. *
  536. ******************************************************************************/
  537.  
  538. static int torus_image_map(EPoint, Image, u, v)
  539. VECTOR EPoint;
  540. IMAGE *Image;
  541. DBL *u, *v;
  542. {
  543.   DBL len, phi, theta;
  544.   DBL r0;
  545.   DBL x = EPoint[X];
  546.   DBL y = EPoint[Y];
  547.   DBL z = EPoint[Z];
  548.  
  549.   r0 = Image->Gradient[X];
  550.  
  551.   /* Determine its angle from the x-axis. */
  552.  
  553.   len = sqrt(x * x + z * z);
  554.  
  555.   if (len == 0.0)
  556.   {
  557.     return 0;
  558.   }
  559.   else
  560.   {
  561.     if (z == 0.0)
  562.     {
  563.       if (x > 0)
  564.       {
  565.         theta = 0.0;
  566.       }
  567.       else
  568.       {
  569.         theta = M_PI;
  570.       }
  571.     }
  572.     else
  573.     {
  574.       theta = acos(x / len);
  575.  
  576.       if (z < 0.0)
  577.       {
  578.         theta = 2.0 * M_PI - theta;
  579.       }
  580.     }
  581.   }
  582.  
  583.   theta = 0.0 - theta;
  584.  
  585.   /* Now rotate about the y-axis to get the point (x, y, z) into the x-y plane. */
  586.  
  587.   x = len - r0;
  588.  
  589.   len = sqrt(x * x + y * y);
  590.  
  591.   phi = acos(-x / len);
  592.  
  593.   if (y > 0.0)
  594.   {
  595.     phi = 2.0 * M_PI - phi;
  596.   }
  597.  
  598.   /* Determine the parametric coordinates. */
  599.  
  600.   theta /= 2.0 * M_PI;
  601.  
  602.   phi /= 2.0 * M_PI;
  603.  
  604.   *u = (-theta * Image->width);
  605.  
  606.   *v = (phi * Image->height);
  607.  
  608.   return 1;
  609. }
  610.  
  611.  
  612.  
  613. /*****************************************************************************
  614. *
  615. * FUNCTION
  616. *
  617. * INPUT
  618. *
  619. * OUTPUT
  620. *
  621. * RETURNS
  622. *
  623. * AUTHOR
  624. *
  625. * DESCRIPTION
  626. *
  627. *   Map a point (x, y, z) on a sphere of radius 1 to a 2-d image. (Or is it the
  628. *   other way around?)
  629. *
  630. * CHANGES
  631. *
  632. ******************************************************************************/
  633.  
  634. static int spherical_image_map(EPoint, Image, u, v)
  635. VECTOR EPoint;
  636. IMAGE *Image;
  637. DBL *u, *v;
  638. {
  639.   DBL len, phi, theta;
  640.   DBL x = EPoint[X];
  641.   DBL y = EPoint[Y];
  642.   DBL z = EPoint[Z];
  643.   DBL rdiv;
  644.   
  645.   /* Make sure this vector is on the unit sphere. */
  646.  
  647.   len = sqrt(x * x + y * y + z * z);
  648.  
  649.   if (len == 0.0)
  650.   {
  651.     return 0;
  652.   }
  653.   else
  654.   {
  655.     rdiv = (1.0 / len);
  656.     x *= rdiv;
  657.     y *= rdiv;
  658.     z *= rdiv;
  659. /*
  660.     x /= len;
  661.     y /= len;
  662.     z /= len;
  663. */
  664.   }
  665.  
  666.   /* Determine its angle from the x-z plane. */
  667.  
  668.   phi = 0.5 + asin(y) / M_PI; /* This will be from 0 to 1 */
  669.  
  670.  
  671.   /* Determine its angle from the point (1, 0, 0) in the x-z plane. */
  672.  
  673.   len = sqrt(x * x + z * z);
  674.  
  675.   if (len == 0.0)
  676.   {
  677.     /* This point is at one of the poles. Any value of xcoord will be ok... */
  678.  
  679.     theta = 0;
  680.   }
  681.   else
  682.   {
  683.     if (z == 0.0)
  684.     {
  685.       if (x > 0)
  686.       {
  687.         theta = 0.0;
  688.       }
  689.       else
  690.       {
  691.         theta = M_PI;
  692.       }
  693.     }
  694.     else
  695.     {
  696.       theta = acos(x / len);
  697.  
  698.       if (z < 0.0)
  699.       {
  700.         theta = 2.0 * M_PI - theta;
  701.       }
  702.     }
  703.  
  704.     theta /= 2.0 * M_PI;  /* This will be from 0 to 1 */
  705.   }
  706.  
  707.   *u = (theta * Image->width);
  708.   *v = (phi * Image->height);
  709.  
  710.   return 1;
  711. }
  712.  
  713. /*
  714.  * 2-D to 3-D Procedural Texture Mapping of a Bitmapped Image onto an Object:
  715.  * 
  716.  * Simplistic planar method of object image projection devised by DKB and AAC.
  717.  * 
  718.  * 1. Transform texture in 3-D space if requested. 2. Determine local object 2-d
  719.  * coords from 3-d coords by <X Y Z> triple. 3. Return pixel color value at
  720.  * that position on the 2-d plane of "Image". 3. Map colour value in Image
  721.  * [0..255] to a more normal colour range [0..1].
  722.  */
  723.  
  724.  
  725.  
  726. /*****************************************************************************
  727. *
  728. * FUNCTION
  729. *
  730. * INPUT
  731. *
  732. * OUTPUT
  733. *
  734. * RETURNS
  735. *
  736. * AUTHOR
  737. *
  738. * DESCRIPTION
  739. *
  740. *   Return 0 if there is no color at this point (i.e. invisible), return 1 if a
  741. *   good mapping is found.
  742. *
  743. * CHANGES
  744. *
  745. ******************************************************************************/
  746.  
  747. static int planar_image_map(EPoint, Image, u, v)
  748. VECTOR EPoint;
  749. IMAGE *Image;
  750. DBL *u, *v;
  751. {
  752.   DBL x = EPoint[X];
  753.   DBL y = EPoint[Y];
  754.   DBL z = EPoint[Z];
  755.  
  756.   if (Image->Gradient[X] != 0.0)
  757.   {
  758.     if ((Image->Once_Flag) && ((x < 0.0) || (x > 1.0)))
  759.     {
  760.       return 0;
  761.     }
  762.  
  763.     if (Image->Gradient[X] > 0)
  764.     {
  765.       *u = fmod(x * Image->width, Image->width);
  766.     }
  767.     else
  768.     {
  769.       *v = fmod(x * Image->height, Image->height);
  770.     }
  771.   }
  772.  
  773.   if (Image->Gradient[Y] != 0.0)
  774.   {
  775.     if ((Image->Once_Flag) && ((y < 0.0) || (y > 1.0)))
  776.     {
  777.       return 0;
  778.     }
  779.  
  780.     if (Image->Gradient[Y] > 0)
  781.     {
  782.       *u = fmod(y * Image->width, Image->width);
  783.     }
  784.     else
  785.     {
  786.       *v = fmod(y * Image->height, Image->height);
  787.     }
  788.   }
  789.  
  790.   if (Image->Gradient[Z] != 0.0)
  791.   {
  792.     if ((Image->Once_Flag) && ((z < 0.0) || (z > 1.0)))
  793.     {
  794.       return 0;
  795.     }
  796.  
  797.     if (Image->Gradient[Z] > 0)
  798.     {
  799.       *u = fmod(z * Image->width, Image->width);
  800.     }
  801.     else
  802.     {
  803.       *v = fmod(z * Image->height, Image->height);
  804.     }
  805.   }
  806.  
  807.   return 1;
  808. }
  809.  
  810.  
  811. /*****************************************************************************
  812. *
  813. * FUNCTION
  814. *
  815. *   map
  816. *
  817. * INPUT
  818. *
  819. *   EPoint   -- 3-D point at which function is evaluated
  820. *   TPattern -- Pattern containing various parameters
  821. *
  822. * OUTPUT
  823. *
  824. *   xcoor, ycoor -- 2-D result
  825. *
  826. * RETURNS
  827. *
  828. *   Map returns 1 if point off of map 0 if on map
  829. *
  830. * AUTHOR
  831. *
  832. *   POV-Ray Team
  833. *
  834. * DESCRIPTION   : Maps a 3-D point to a 2-D point depending upon map type
  835. *
  836. * CHANGES
  837. *
  838. ******************************************************************************/
  839.  
  840. static int map(EPoint, TPattern, xcoor, ycoor)
  841. VECTOR EPoint;
  842. TPATTERN *TPattern;
  843. DBL *xcoor, *ycoor;
  844. {
  845.   IMAGE *Image = TPattern->Vals.Image;
  846.  
  847.   /* Now determine which mapper to use. */
  848.  
  849.   switch (Image->Map_Type)
  850.   {
  851.     case PLANAR_MAP:
  852.  
  853.       if (!planar_image_map(EPoint, Image, xcoor, ycoor))
  854.       {
  855.         return (1);
  856.       }
  857.  
  858.       break;
  859.  
  860.     case SPHERICAL_MAP:
  861.  
  862.       if (!spherical_image_map(EPoint, Image, xcoor, ycoor))
  863.       {
  864.         return (1);
  865.       }
  866.  
  867.       break;
  868.  
  869.     case CYLINDRICAL_MAP:
  870.  
  871.       if (!cylindrical_image_map(EPoint, Image, xcoor, ycoor))
  872.       {
  873.         return (1);
  874.       }
  875.  
  876.       break;
  877.  
  878.     case TORUS_MAP:
  879.  
  880.       if (!torus_image_map(EPoint, Image, xcoor, ycoor))
  881.       {
  882.         return (1);
  883.       }
  884.  
  885.       break;
  886.  
  887.     default:
  888.  
  889.       if (!planar_image_map(EPoint, Image, xcoor, ycoor))
  890.       {
  891.         return (1);
  892.       }
  893.  
  894.       break;
  895.   }
  896.  
  897.   /* Now make sure the point is on the image */
  898.  
  899.   *ycoor += Small_Tolerance;
  900.   *xcoor += Small_Tolerance;
  901.  
  902.   /* Compensate for y coordinates on the images being upsidedown */
  903.  
  904.   *ycoor = (DBL)Image->iheight - *ycoor;
  905.  
  906.   if (*xcoor < 0.0)
  907.   {
  908.     *xcoor += (DBL)Image->iwidth;
  909.   }
  910.   else
  911.   {
  912.     if (*xcoor >= (DBL)Image->iwidth)
  913.     {
  914.       *xcoor -= (DBL)Image->iwidth;
  915.     }
  916.   }
  917.  
  918.   if (*ycoor < 0.0)
  919.   {
  920.     *ycoor += (DBL)Image->iheight;
  921.   }
  922.   else
  923.   {
  924.     if (*ycoor >= (DBL)Image->iheight)
  925.     {
  926.       *ycoor -= (DBL)Image->iheight;
  927.     }
  928.   }
  929.  
  930.   if ((*xcoor >= (DBL)Image->iwidth) ||
  931.       (*ycoor >= (DBL)Image->iheight) ||
  932.       (*xcoor < 0.0) || (*ycoor < 0.0))
  933.   {
  934.     Error("Picture index out of range.");
  935.   }
  936.  
  937.   return (0);
  938. }
  939.  
  940.  
  941.  
  942. /*****************************************************************************
  943. *
  944. * FUNCTION
  945. *
  946. * INPUT
  947. *
  948. * OUTPUT
  949. *
  950. * RETURNS
  951. *
  952. * AUTHOR
  953. *
  954. * DESCRIPTION
  955. *
  956. * CHANGES
  957. *
  958. ******************************************************************************/
  959.  
  960. static void no_interpolation(Image, xcoor, ycoor, colour, index)
  961. IMAGE *Image;
  962. DBL xcoor, ycoor;
  963. COLOUR colour;
  964. int *index;
  965. {
  966.   IMAGE_LINE *line;
  967.   int iycoor, ixcoor;
  968.   IMAGE_COLOUR *map_colour;
  969.  
  970.   if (xcoor < 0.0)
  971.   {
  972.     xcoor += (DBL)Image->iwidth;
  973.   }
  974.   else
  975.   {
  976.     if (xcoor >= (DBL)Image->iwidth)
  977.     {
  978.       xcoor -= (DBL)Image->iwidth;
  979.     }
  980.   }
  981.  
  982.   if (ycoor < 0.0)
  983.   {
  984.     ycoor += (DBL)Image->iheight;
  985.   }
  986.   else
  987.   {
  988.     if (ycoor >= (DBL)Image->iheight)
  989.     {
  990.       ycoor -= (DBL)Image->iheight;
  991.     }
  992.   }
  993.  
  994.   iycoor = (int)ycoor;
  995.   ixcoor = (int)xcoor;
  996.  
  997.   if (Image->Colour_Map == NULL)
  998.   {
  999.     line = &Image->data.rgb_lines[iycoor];
  1000.  
  1001.     colour[RED] += (DBL)line->red[ixcoor] / 255.0;
  1002.     colour[GREEN] += (DBL)line->green[ixcoor] / 255.0;
  1003.     colour[BLUE] += (DBL)line->blue[ixcoor] / 255.0;
  1004.     if (line->transm != NULL)
  1005.     {
  1006.       colour[TRANSM] += (DBL)line->transm[ixcoor] / 255.0;
  1007.     }
  1008.  
  1009.     *index = -1;
  1010.   }
  1011.   else
  1012.   {
  1013.     *index = Image->data.map_lines[iycoor][ixcoor];
  1014.  
  1015.     map_colour = &Image->Colour_Map[*index];
  1016.  
  1017.     colour[RED] += (DBL)map_colour->Red / 255.0;
  1018.     colour[GREEN] += (DBL)map_colour->Green / 255.0;
  1019.     colour[BLUE] += (DBL)map_colour->Blue / 255.0;
  1020.     colour[FILTER] += (DBL)map_colour->Filter / 255.0;
  1021.     colour[TRANSM] += (DBL)map_colour->Transmit / 255.0;
  1022.   }
  1023. }
  1024.  
  1025.  
  1026.  
  1027. /*****************************************************************************
  1028. *
  1029. * FUNCTION
  1030. *
  1031. * INPUT
  1032. *
  1033. * OUTPUT
  1034. *
  1035. * RETURNS
  1036. *
  1037. * AUTHOR
  1038. *
  1039. * DESCRIPTION
  1040. *
  1041. * CHANGES
  1042. *
  1043. ******************************************************************************/
  1044.  
  1045. /* Interpolate color and filter values when mapping */
  1046.  
  1047. static void Interp(Image, xcoor, ycoor, colour, index)
  1048. IMAGE *Image;
  1049. DBL xcoor, ycoor;
  1050. COLOUR colour;
  1051. int *index;
  1052. {
  1053.   int iycoor, ixcoor, i;
  1054.   int Corners_Index[4];
  1055.   DBL Index_Crn[4];
  1056.   COLOUR Corner_Colour[4];
  1057.   DBL Red_Crn[4];
  1058.   DBL Green_Crn[4];
  1059.   DBL Blue_Crn[4];
  1060.   DBL Filter_Crn[4];
  1061.   DBL Transm_Crn[4];
  1062.   DBL val1, val2, val3, val4, val5;
  1063.  
  1064.   val1 = val2 = val3 = val4 = val5 = 0.0;
  1065.  
  1066.   iycoor = (int)ycoor;
  1067.   ixcoor = (int)xcoor;
  1068.  
  1069.   for (i = 0; i < 4; i++)
  1070.   {
  1071.     Make_ColourA(Corner_Colour[i], 0.0, 0.0, 0.0, 0.0, 0.0);
  1072.   }
  1073.  
  1074.   /* OK, now that you have the corners, what are you going to do with them? */
  1075.  
  1076.   if (Image->Interpolation_Type == BILINEAR)
  1077.   {
  1078.     no_interpolation(Image, (DBL)ixcoor + 1, (DBL)iycoor, Corner_Colour[0], &Corners_Index[0]);
  1079.     no_interpolation(Image, (DBL)ixcoor, (DBL)iycoor, Corner_Colour[1], &Corners_Index[1]);
  1080.     no_interpolation(Image, (DBL)ixcoor + 1, (DBL)iycoor - 1, Corner_Colour[2], &Corners_Index[2]);
  1081.     no_interpolation(Image, (DBL)ixcoor, (DBL)iycoor - 1, Corner_Colour[3], &Corners_Index[3]);
  1082.  
  1083.     for (i = 0; i < 4; i++)
  1084.     {
  1085.       Red_Crn[i] = Corner_Colour[i][RED];
  1086.       Green_Crn[i] = Corner_Colour[i][GREEN];
  1087.       Blue_Crn[i] = Corner_Colour[i][BLUE];
  1088.       Filter_Crn[i] = Corner_Colour[i][FILTER];
  1089.       Transm_Crn[i] = Corner_Colour[i][TRANSM];
  1090.  
  1091.       /*
  1092.        * Debug_Info("Crn %d = %lf %lf
  1093.        * %lf\n",i,Red_Crn[i],Blue_Crn[i],Green_Crn[i]);
  1094.        */
  1095.     }
  1096.  
  1097.     val1 = bilinear(Red_Crn, xcoor, ycoor);
  1098.     val2 = bilinear(Green_Crn, xcoor, ycoor);
  1099.     val3 = bilinear(Blue_Crn, xcoor, ycoor);
  1100.     val4 = bilinear(Filter_Crn, xcoor, ycoor);
  1101.     val5 = bilinear(Transm_Crn, xcoor, ycoor);
  1102.   }
  1103.  
  1104.   if (Image->Interpolation_Type == NORMALIZED_DIST)
  1105.   {
  1106.     no_interpolation(Image, (DBL)ixcoor, (DBL)iycoor - 1, Corner_Colour[0], &Corners_Index[0]);
  1107.     no_interpolation(Image, (DBL)ixcoor + 1, (DBL)iycoor - 1, Corner_Colour[1], &Corners_Index[1]);
  1108.     no_interpolation(Image, (DBL)ixcoor, (DBL)iycoor, Corner_Colour[2], &Corners_Index[2]);
  1109.     no_interpolation(Image, (DBL)ixcoor + 1, (DBL)iycoor, Corner_Colour[3], &Corners_Index[3]);
  1110.  
  1111.     for (i = 0; i < 4; i++)
  1112.     {
  1113.       Red_Crn[i] = Corner_Colour[i][RED];
  1114.       Green_Crn[i] = Corner_Colour[i][GREEN];
  1115.       Blue_Crn[i] = Corner_Colour[i][BLUE];
  1116.       Filter_Crn[i] = Corner_Colour[i][FILTER];
  1117.       Transm_Crn[i] = Corner_Colour[i][TRANSM];
  1118.  
  1119.       /*
  1120.        * Debug_Info("Crn %d = %lf %lf
  1121.        * %lf\n",i,Red_Crn[i],Blue_Crn[i],Green_Crn[i]);
  1122.        */
  1123.     }
  1124.  
  1125.     val1 = norm_dist(Red_Crn, xcoor, ycoor);
  1126.     val2 = norm_dist(Green_Crn, xcoor, ycoor);
  1127.     val3 = norm_dist(Blue_Crn, xcoor, ycoor);
  1128.     val4 = norm_dist(Filter_Crn, xcoor, ycoor);
  1129.     val5 = norm_dist(Transm_Crn, xcoor, ycoor);
  1130.   }
  1131.  
  1132.   colour[RED] += val1;
  1133.   colour[GREEN] += val2;
  1134.   colour[BLUE] += val3;
  1135.   colour[FILTER] += val4;
  1136.   colour[TRANSM] += val5;
  1137.  
  1138.   /* Debug_Info("Final = %lf %lf %lf\n",val1,val2,val3);  */
  1139.   /* use bilinear for index try average later */
  1140.  
  1141.   for (i = 0; i < 4; i++)
  1142.   {
  1143.     Index_Crn[i] = (DBL)Corners_Index[i];
  1144.   }
  1145.  
  1146.   if (Image->Interpolation_Type == BILINEAR)
  1147.   {
  1148.     *index = (int)(bilinear(Index_Crn, xcoor, ycoor) + 0.5);
  1149.   }
  1150.  
  1151.   if (Image->Interpolation_Type == NORMALIZED_DIST)
  1152.   {
  1153.     *index = (int)(norm_dist(Index_Crn, xcoor, ycoor) + 0.5);
  1154.   }
  1155. }
  1156.  
  1157.  
  1158.  
  1159. /*****************************************************************************
  1160. *
  1161. * FUNCTION
  1162. *
  1163. * INPUT
  1164. *
  1165. * OUTPUT
  1166. *
  1167. * RETURNS
  1168. *
  1169. * AUTHOR
  1170. *
  1171. * DESCRIPTION
  1172. *
  1173. * CHANGES
  1174. *
  1175. ******************************************************************************/
  1176.  
  1177. /* These interpolation techniques are taken from an article by */
  1178. /* Girish T. Hagan in the C Programmer's Journal V 9 No. 8 */
  1179. /* They were adapted for POV-Ray by CdW */
  1180.  
  1181. static DBL bilinear(corners, x, y)
  1182. DBL *corners, x, y;
  1183. {
  1184.   DBL p, q;
  1185.   DBL val;
  1186.  
  1187.   p = x - (int)x;
  1188.   q = y - (int)y;
  1189.  
  1190.   if ((p == 0.0) && (q == 0.0))
  1191.   {
  1192.     return (*corners);  /* upper left */
  1193.   }
  1194.  
  1195.   val = (p * q * *corners) + (q * (1 - p) * *(corners + 1)) +
  1196.     (p * (1 - q) * *(corners + 2)) + ((1 - p) * (1 - q) * *(corners + 3));
  1197.  
  1198.   return (val);
  1199. }
  1200.  
  1201.  
  1202.  
  1203.  
  1204. /*****************************************************************************
  1205. *
  1206. * FUNCTION
  1207. *
  1208. * INPUT
  1209. *
  1210. * OUTPUT
  1211. *
  1212. * RETURNS
  1213. *
  1214. * AUTHOR
  1215. *
  1216. * DESCRIPTION
  1217. *
  1218. * CHANGES
  1219. *
  1220. ******************************************************************************/
  1221.  
  1222. #define MAX_PTS 4
  1223. #define PYTHAGOREAN_SQ(a,b)  ( (a)*(a) + (b)*(b) )
  1224.  
  1225. static DBL norm_dist(corners, x, y)
  1226. DBL *corners, x, y;
  1227. {
  1228.   register int i;
  1229.  
  1230.   DBL p, q;
  1231.   DBL wts[MAX_PTS];
  1232.   DBL sum_inv_wts = 0.0;
  1233.   DBL sum_I = 0.0;
  1234.   DBL rdiv;
  1235.  
  1236.   p = x - (int)x;
  1237.   q = y - (int)y;
  1238.  
  1239.   if ((p == 0.0) && (q == 0.0))
  1240.   {
  1241.     return (*corners);  /* upper left */
  1242.   }
  1243.  
  1244.   wts[0] = PYTHAGOREAN_SQ(p, q);
  1245.   wts[1] = PYTHAGOREAN_SQ(1 - p, q);
  1246.   wts[2] = PYTHAGOREAN_SQ(p, 1 - q);
  1247.   wts[3] = PYTHAGOREAN_SQ(1 - p, 1 - q);
  1248.  
  1249.   for (i = 0; i < MAX_PTS; i++)
  1250.   {
  1251.     rdiv = (1.0 / wts[i]);
  1252.     sum_inv_wts += rdiv;
  1253.     sum_I += *(corners + i) * rdiv;
  1254. /*
  1255.     sum_inv_wts += 1 / wts[i];
  1256.     sum_I += *(corners + i) / wts[i];
  1257. */
  1258.   }
  1259.  
  1260.   return (sum_I / sum_inv_wts);
  1261. }
  1262.  
  1263.  
  1264.  
  1265. /*****************************************************************************
  1266. *
  1267. * FUNCTION
  1268. *
  1269. *   Create_Image
  1270. *
  1271. * INPUT
  1272. *
  1273. * OUTPUT
  1274. *
  1275. * RETURNS
  1276. *
  1277. * AUTHOR
  1278. *
  1279. *   POV-Ray Team
  1280. *
  1281. * DESCRIPTION
  1282. *
  1283. *   -
  1284. *
  1285. * CHANGES
  1286. *
  1287. *   -
  1288. *
  1289. ******************************************************************************/
  1290.  
  1291. IMAGE *Create_Image()
  1292. {
  1293.   IMAGE *Image;
  1294.  
  1295.   Image = (IMAGE *) POV_MALLOC(sizeof(IMAGE), "image file");
  1296.  
  1297.   Image->References = 1;
  1298.  
  1299.   Image->File_Type = NO_FILE;
  1300.  
  1301.   Image->Map_Type = PLANAR_MAP;
  1302.  
  1303.   Image->Interpolation_Type = NO_INTERPOLATION;
  1304.  
  1305.   Image->Once_Flag = FALSE;
  1306.  
  1307.   Image->Use_Colour_Flag = FALSE;
  1308.  
  1309.   Make_Vector(Image->Gradient, 1.0, -1.0, 0.0);
  1310.  
  1311.   return (Image);
  1312. }
  1313.  
  1314.  
  1315.  
  1316. /*****************************************************************************
  1317. *
  1318. * FUNCTION
  1319. *
  1320. *   Copy_Image
  1321. *
  1322. * INPUT
  1323. *
  1324. * OUTPUT
  1325. *
  1326. * RETURNS
  1327. *
  1328. * AUTHOR
  1329. *
  1330. *   POV-Ray Team
  1331. *
  1332. * DESCRIPTION
  1333. *
  1334. *   -
  1335. *
  1336. * CHANGES
  1337. *
  1338. *   -
  1339. *
  1340. ******************************************************************************/
  1341.  
  1342. IMAGE *Copy_Image(Old)
  1343. IMAGE *Old;
  1344. {
  1345.   if (Old != NULL)
  1346.   {
  1347.     Old->References++;
  1348.   }
  1349.  
  1350.   return (Old);
  1351. }
  1352.  
  1353.  
  1354.  
  1355. /*****************************************************************************
  1356. *
  1357. * FUNCTION
  1358. *
  1359. *   Destroy_Image
  1360. *
  1361. * INPUT
  1362. *
  1363. * OUTPUT
  1364. *
  1365. * RETURNS
  1366. *
  1367. * AUTHOR
  1368. *
  1369. *   POV-Ray Team
  1370. *
  1371. * DESCRIPTION
  1372. *
  1373. *   -
  1374. *
  1375. * CHANGES
  1376. *
  1377. *   -
  1378. *
  1379. ******************************************************************************/
  1380.  
  1381. void Destroy_Image(Image)
  1382. IMAGE *Image;
  1383. {
  1384.   int i;
  1385.  
  1386.   if ((Image == NULL) || (--(Image->References) > 0))
  1387.   {
  1388.     return;
  1389.   }
  1390.  
  1391.   if (Image->Colour_Map != NULL)
  1392.   {
  1393.     POV_FREE(Image->Colour_Map);
  1394.  
  1395.     Image->Colour_Map = NULL;
  1396.  
  1397.     if (Image->data.map_lines != NULL)
  1398.     {
  1399.       for (i = 0; i < Image->iheight; i++)
  1400.       {
  1401.         POV_FREE(Image->data.map_lines[i]);
  1402.       }
  1403.  
  1404.       POV_FREE(Image->data.map_lines);
  1405.  
  1406.       Image->data.map_lines = NULL;
  1407.     }
  1408.   }
  1409.   else
  1410.   {
  1411.     if (Image->data.rgb_lines != NULL)
  1412.     {
  1413.       for (i = 0; i < Image->iheight; i++)
  1414.       {
  1415.         POV_FREE(Image->data.rgb_lines[i].red);
  1416.         POV_FREE(Image->data.rgb_lines[i].green);
  1417.         POV_FREE(Image->data.rgb_lines[i].blue);
  1418.  
  1419.         if (Image->data.rgb_lines[i].transm != NULL)
  1420.         {
  1421.           POV_FREE(Image->data.rgb_lines[i].transm);
  1422.         }
  1423.       }
  1424.  
  1425.       POV_FREE(Image->data.rgb_lines);
  1426.  
  1427.       Image->data.rgb_lines = NULL;
  1428.     }
  1429.   }
  1430.  
  1431.   POV_FREE(Image);
  1432. }
  1433.